#include <vector>
#include <ncurses.h>

#include "Curses.h"

#include "Player.h"
#include "Item.h"
#include "Level.h"
#include "MapWindow.h"

#include "Prompt.h"
#include "PickupPrompt.h"
#include "InventoryWindow.h"

#include "Directions.h"

#include "Core.h"

Core::Core() : m_turnNumber(0) {
	m_currentLevel = new Level;
	m_currentMapWindow = new MapWindow(42, 22, 1, 1, m_currentLevel);
	Curses::instance().pushWindow(m_currentMapWindow);

	m_player = Player::createPlayer(5, 5);
	m_player->setCurrentLevel(m_currentLevel);
	
	m_entityManager.addCharacter(m_player);
	
	for (int i = 0; i < 33; i++) {
		Item* testItem = Item::createTestWeapon();
		testItem->setCurrentLevel(m_currentLevel);
		m_entityManager.addItem(testItem);
	}
}

Core& Core::instance() {
	static Core core;
	return core;
}

void Core::inputLoop() {

	Curses curses = Curses::instance();

	while (true) {
	
		// We only want to update the world if the player
		// actually did something.
		bool action = false;
	
		if (m_player->remainingActionPoints() > 0) {
			// Only allow actions if player actually has points left.
	
			int key = Curses::instance().getchar();
	
			if (key == '8' || key == KEY_UP)	action = m_player->step(NORTH);
			if (key == '2' || key == KEY_DOWN)	action = m_player->step(SOUTH);
			if (key == '4' || key == KEY_LEFT)	action = m_player->step(WEST);
			if (key == '6' || key == KEY_RIGHT)	action = m_player->step(EAST);
			if (key == '7')		action = m_player->step(NORTH_WEST);
			if (key == '9')		action = m_player->step(NORTH_EAST);
			if (key == '1')		action = m_player->step(SOUTH_WEST);
			if (key == '3')		action = m_player->step(SOUTH_EAST);
	
			if (key == ',')
				action = tryPickup();
	
			if (key == 'i') {
				InventoryWindow* inventoryWindow = new InventoryWindow(&m_player->inventory());
				inventoryWindow->show();
				delete inventoryWindow;
			}
			

			if (key == 'Q') {
				Prompt* prompt = new Prompt("Really quit?");
				if (prompt->show())
					break;
				delete prompt;
			}
	
		}
	
		m_currentMapWindow->output();
		m_entityManager.outputEntities(m_currentLevel);
		curses.refresh();
	
//		if (action) {
			// TODO: Update the world.			
	
			// Check if there are any character in the world that
			// has additional actions. If not, reset all aciton points
			// and increase the turn number.
			if (!m_entityManager.actionsRemaining()) {
				m_entityManager.resetActions();
				m_turnNumber++;
			}
//		}
	}
	
}

bool Core::tryPickup() {
	std::vector<Item *> items =
		m_entityManager.getItemsAt(m_player->coord().x, m_player->coord().y, m_currentLevel);

	if (items.size() > 0) {
		bool success = false;
		if (items.size() == 1) {
			success = m_player->pickup(items[0]);
			if (success)
				m_entityManager.removeItem(items[0]);
		} else {
			PickupPrompt* pickupPrompt = new PickupPrompt(items);
			std::vector<Item *> result = pickupPrompt->show();
			delete pickupPrompt;
			
			for (size_t i = 0; i < result.size(); i++) {
				success = m_player->pickup(result[i]);
				
				// As soon as we reach an item that cant be picked
				// up, break and inform player.
				if (!success)
					break;
				else
					m_entityManager.removeItem(items[i]);
			}
			
		}

		if (!success) {
			// TODO: Message: You can't pick this up.
		}
		
		return success;
	} else {
		// TODO: Message: There's nothing here.
		return false;
	}
}
